1 module hip.math.utils; 2 import hip.math.vector; 3 4 ///There are some errors occurring when compiling with LDC 5 public import core.math: sqrt, cos, sin; 6 7 pure @safe nothrow @nogc: 8 9 enum PI = 3.14159; 10 enum PI_2 = PI/2; 11 enum PI_4 = PI/4; 12 13 enum RAD_TO_DEG = 180/PI; 14 enum DEG_TO_RAD = PI/180; 15 16 float radToDeg(float radians) 17 { 18 assert(radians == radians); //float.nan check 19 return radians*RAD_TO_DEG; 20 } 21 float degToRad(float degrees) 22 { 23 assert(degrees == degrees); //float.nan check 24 return DEG_TO_RAD * degrees; 25 } 26 27 int getClosestMultiple(int from, int to) 28 { 29 float temp = to/cast(float)from; 30 int tempI = to/from; 31 32 if(temp == tempI) 33 return from * tempI; 34 else 35 { 36 temp-= tempI; 37 if(temp <= 0.5) 38 return from*tempI; 39 else 40 return from*(tempI+1); 41 } 42 } 43 44 bool approximatelyEqual(in float from, in float to, in float error = 0.01) 45 { 46 float diff = from - to; 47 return diff >= -error && diff <= error; 48 } 49 50 pragma(inline, true) int round(float f) pure @nogc @safe nothrow {return f > 0 ? cast(int)(f+0.5) : cast(int)(f-0.5);} 51 52 ///Bit twiddling hacks 53 uint roundPow2(uint n) 54 { 55 if(n == 0) return 1; 56 n--; 57 n |= n >> 1; 58 n |= n >> 2; 59 n |= n >> 4; 60 n |= n >> 8; 61 n |= n >> 16; 62 return n + 1; 63 } 64 65 /** 66 * 67 * Params: 68 * from = From which value to interpolate 69 * to = To which value 70 * t = The T of interpolation 71 * Returns: 72 */ 73 float lerp(float from, float to, float t) 74 { 75 return (1.0f-t)*from + t*to; 76 } 77 78 bool isPowerOf2(size_t num) 79 { 80 return (num & (num - 1)) == 0; 81 } 82 83 enum dipsPerInch = 96.0f; 84 int convertDipsToPixels(float dips, float dpi = 96.0f) //96 is Windows convention 85 { 86 return cast(int)(dips * dpi / dipsPerInch + 0.5f); //Round to nearest integer 87 } 88 89 float physicalPixelToDIPs(int pixels, float dpi = 96.0f) 90 { 91 return pixels/(dpi/dipsPerInch); 92 } 93 94 enum AxisNavigation{xy, yz, xz, zx, zy, yx} 95 96 Vector3 toCircleBounds(Vector3 v, float angle, AxisNavigation axis=AxisNavigation.xy) 97 { 98 float mag = v.mag; 99 final switch(axis) with(AxisNavigation) 100 { 101 case xy: 102 v.x = cos(angle)*mag; 103 v.y = sin(angle)*mag; 104 break; 105 case yz: 106 v.y = cos(angle)*mag; 107 v.z = sin(angle)*mag; 108 break; 109 case xz: 110 v.x = cos(angle)*mag; 111 v.z = sin(angle)*mag; 112 break; 113 case zx: 114 v.z = cos(angle)*mag; 115 v.x = sin(angle)*mag; 116 break; 117 case zy: 118 v.z = cos(angle)*mag; 119 v.y = sin(angle)*mag; 120 break; 121 case yx: 122 v.y = cos(angle)*mag; 123 v.x = sin(angle)*mag; 124 break; 125 } 126 return v; 127 } 128 129 pragma(inline, true) 130 T abs(T)(T val) pure nothrow @safe @nogc 131 { 132 return val < 0 ? -val : val; 133 } 134 135 T min(T)(in T[] values ...) pure nothrow @safe @nogc 136 { 137 T v = values[0]; 138 for(int i = 1; i < values.length; i++) 139 if(values[i] < v) 140 v = values[i]; 141 return v; 142 } 143 144 T max(T)(in T[] values ...) pure nothrow @safe @nogc 145 { 146 T v = values[0]; 147 for(int i = 1; i < values.length; i++) 148 if(values[i] > v) 149 v = values[i]; 150 return v; 151 } 152 153 T sum(T)(in T[] values ...) pure nothrow @safe @nogc 154 { 155 T sum = 0; 156 foreach(v; values) sum+= v; 157 return sum; 158 } 159 160 161 float floor(in float val) pure nothrow @safe @nogc{return floor!float(val);} 162 T floor(T)(in float val) pure nothrow @safe @nogc 163 { 164 return cast(T)(cast(int)val); 165 } 166 float ceil(in float val) pure nothrow @safe @nogc {return ceil!float(val);} 167 T ceil(T)(in float val) pure nothrow @safe @nogc 168 { 169 return cast(T)(cast(int)(val + 0.9999999)); 170 } 171 172 173 T clamp(T)(T value, T min, T max) pure nothrow @safe @nogc 174 { 175 return value < min ? min : value > max ? max : value; 176 } 177 178 pragma(inline)T abs(T)(in T value){return value < 0 ? -value : value;} 179 180 int greatestCommonDivisor(int a, int b) 181 { 182 int res; 183 int lastRes; 184 do 185 { 186 res = a % b; 187 lastRes = b; 188 a = b; 189 b = res; 190 } while(res != 0); 191 192 return lastRes; 193 } 194 195 Vector2 quadraticBezier(float x0, float y0, float x1, float y1, float x2, float y2, float t) 196 { 197 float dtT = (1.0f-t); 198 float dtTSquare = dtT*dtT; 199 float tSq = t*t; 200 return Vector2( 201 dtTSquare*x0 + 2*t*dtT*x1 + tSq*x2, 202 dtTSquare*y0 + 2*t*dtT*y1 + tSq*y2 203 ); 204 } 205 206 pragma(inline) Vector2 quadraticBezier(Vector2 p0, Vector2 p1, Vector2 p2, float t) 207 { 208 return quadraticBezier(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, t); 209 } 210 211 Vector2 cubicBezier(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float t) 212 { 213 float dtT = 1.0f-t; 214 float dtTSq = dtT*dtT; 215 float dtTCub = dtTSq*dtT; 216 float tSq = t*t; 217 float tCub = tSq*t; 218 219 return Vector2( 220 dtTCub*x0 + 3*t*dtTSq*x1 + 3*tSq*dtT*x2 + tCub*x3, 221 dtTCub*y0 + 3*t*dtTSq*y1 + 3*tSq*dtT*y2 + tCub*y3, 222 ); 223 } 224 225 pragma(inline) Vector2 cubicBezier(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3, float t) 226 { 227 return cubicBezier(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, t); 228 }